#include "StdAfx.h"
#include <LitEditorDialog.h>
#include "LitRoot.h"


namespace Lit
{
	namespace Editor
	{
		StringMapConnecter::StringMapConnecter( const StringMapReturn::MapType & settings, QTableWidget * table )
			: QObject( table )
			, mSettings(settings)

			, mInitialSettings(settings)
			, mTable( table )
		{ 
			connect( table, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(itemChanged(QTableWidgetItem*)) );
		}
		StringMapConnecter::~StringMapConnecter()
		{}

		void StringMapConnecter::map( QTableWidgetItem * item, QWidget* w , const char * widget_emitter, const char * this_receiver )
		{
			mMapping[w] = item;
			connect( w, widget_emitter, this, this_receiver );
		}

		QTableWidgetItem * StringMapConnecter::findItem( QWidget * from )
		{
			for( auto i=mMapping.begin(); i!=mMapping.end(); i++ )
				if( i->first == from ) return i->second;
			return NULL;
		}
				
		std::unordered_map<QWidget*, QTableWidgetItem*>::iterator StringMapConnecter::findMapping( size_t row )
		{
			for( auto i=mMapping.begin(); i!=mMapping.end(); i++ )
				if( i->second && i->second->row() == row ) 
					return i;
			return mMapping.end();
		}
		std::unordered_map<QWidget*, QTableWidgetItem*>::const_iterator StringMapConnecter::findMapping( size_t row ) const
		{
			for( auto i=mMapping.begin(); i!=mMapping.end(); i++ )
				if( i->second && i->second->row() == row ) 
					return i;
			return mMapping.end();
		}
		const std::unordered_map<QWidget*, QTableWidgetItem*>& StringMapConnecter::getMapping() const{return mMapping;}
		std::unordered_map<QWidget*, QTableWidgetItem*>& StringMapConnecter::getMapping(){ return mMapping; }

		const StringMapReturn::MapType& StringMapConnecter::getSettings() const{return mSettings;}
		StringMapReturn::MapType& StringMapConnecter::getSettings(){ return mSettings; }

		const StringMapReturn::MapType& StringMapConnecter::getInitialSettings() const{return mInitialSettings;}
		StringMapReturn::MapType& StringMapConnecter::getInitialSettings(){ return mInitialSettings; }

		void StringMapConnecter::itemChanged( QTableWidgetItem * item )
		{
			if( item->row() >= mTable->rowCount() ) return;
			QTableWidgetItem * ni = mTable->item( item->row(), 0 );
			QTableWidgetItem * vi = mTable->item( item->row(), 0 );
			if( !ni || !vi ) return;
			std::string n = ni->text().toStdString();
			std::string v = vi->text().toStdString();
			mSettings[n] = v;
			findMapping(item->row())->first->setEnabled( true );
			LIT_LOG_DBG("Setting '"+n+"' changed to "+v);
		}
		void StringMapConnecter::on_restoreDefault_triggered( )
		{
			QPushButton * sendr = (QPushButton*)sender();
			if( !sendr ) return;
			QTableWidgetItem * itm = findItem( sendr );
			if( !itm ) return;
			QTableWidgetItem* nitem = mTable->item( itm->row(), 0 );
			QTableWidgetItem* vitem = mTable->item( itm->row(), 1 );
			if( !nitem || !vitem ) return;
			vitem->setText( TO_QT(mInitialSettings.find(FROM_QT(nitem->text()))!=mInitialSettings.end()?mInitialSettings[FROM_QT(nitem->text())]:"") );
		}
		

		Dialog::Dialog( const std::string &title, const QIcon &icon, QWidget * parent ) : QDialog( parent )
		{
			QVBoxLayout * lay = new QVBoxLayout( this );
			mLayout = new QFormLayout( this );
			mBottomLayout = new QHBoxLayout( this );
				
			mButtons = new QDialogButtonBox( QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, this );
			mBottomLayout->addWidget( mButtons );

			lay->addLayout( mLayout );
			lay->addLayout( mBottomLayout );
			setLayout( lay );

			connect( mButtons, SIGNAL(accepted()), (QDialog*)this, SLOT(accept()) );
			connect( mButtons, SIGNAL(rejected()), (QDialog*)this, SLOT(reject()) );

			setMinimumSize( 150, 90 );
			setWindowTitle( TO_QT(title) );
			setWindowIcon( icon );

			QStyleFactory fac;
			QStyle * style = fac.create("windowsvista");
			if( !style ) style = fac.create("fusion");
			setStyle( style );
		}
		Dialog::~Dialog( ){
			delete mBottomLayout, mBottomLayout = NULL;
			delete mLayout, mLayout = NULL;
		}
			
		QWidget* Dialog::addRow( QWidget * widget ) { mLayout->insertRow( mLayout->rowCount(), widget ); return widget; }
		QWidget* Dialog::addRow( const std::string &name, QWidget * widget ) { mLayout->insertRow( mLayout->rowCount(), TO_QT(name), widget); return widget; }
		QLayout* Dialog::addRow( QLayout * lay ) { mLayout->insertRow( mLayout->rowCount(), lay ); return lay; }
		QLayout* Dialog::addRow( const std::string &name, QLayout * lay ) { mLayout->insertRow( mLayout->rowCount(), TO_QT(name), lay ); return lay; }
		void Dialog::clear(){ 
			for( int i=0; i<mLayout->count(); i++ )
			{
				QLayoutItem * itm = mLayout->takeAt( i );
				delete itm, itm = NULL;
			}
		}
		
		QDialogButtonBox* Dialog::getButtons(){ return mButtons; }
		const QDialogButtonBox* Dialog::getButtons() const{ return mButtons; }
		QFormLayout * Dialog::getLayout(){return mLayout; }
		const QFormLayout * Dialog::getLayout() const{return mLayout; }
		QIcon Dialog::grabIcon( IconType ico )
		{
			switch( ico )
			{
			case DI_WARNING:
				return QIcon( ":/resources/dlg_warning.png" );
			case DI_EXCLAMATION:
				return QIcon( ":/resources/dlg_exclamation.png" );
			case DI_CRITICAL:
				return QIcon( ":/resources/dlg_critical.png" );
			case DI_QUESTION:
				return QIcon( ":/resources/dlg_question.png" );
			case DI_INFORMATION:
				return QIcon( ":/resources/dlg_information.png" );
			case DI_SETTINGS:
				return QIcon( ":/resources/dlg_settings.png" );
			default:
				return QIcon();
			}
		}
		
		QStyle* Dialog::changeStyle( QWidget* parent, const std::string &title, bool apply_to_qapp )
		{
			QDialog *w = new QDialog(parent);
			QGridLayout * lay = new QGridLayout(w);
			QDialogButtonBox * box = new QDialogButtonBox(w);
			QComboBox * cb = new QComboBox(w);
			lay->addWidget( cb );
			lay->addWidget( box );

			box->setOrientation( Qt::Horizontal );
			box->setCenterButtons(true);
			box->addButton( QDialogButtonBox::Ok );
			w->connect( box, SIGNAL(accepted()), w, SLOT(accept()) );

			QStyleFactory fac;
			QStringList k( fac.keys() );
			int id = 0;
			for( auto i=k.begin(); i!=k.end(); i++ )
			{
				cb->addItem( *i );
			}
			cb->setCurrentIndex( 0 );
			QStyle* s(fac.create( cb->currentText() ));
			if( w->exec() == QDialog::Accepted && apply_to_qapp )
				qApp->setStyle( s );
			return s;
		}

		StringReturn Dialog::ask( QWidget * parent, const std::string &title, const std::string &question, const std::string &default_val, IconType type )
		{
			Dialog * dlg( new Dialog( title, grabIcon(type), parent) );
			dlg->addRow( new QLabel( TO_QT(question), dlg ) );
			QLineEdit * edit = (QLineEdit*)dlg->addRow( new QLineEdit(TO_QT(default_val), dlg) );
			edit->setFocus();
			edit->setSelection( 0, default_val.size() );
			dlg->getButtons()->button( QDialogButtonBox::Ok )->setShortcut( Qt::Key_Return );

			StringReturn ret((StringReturn::Code)dlg->exec());
			
			if( ret.accepted() ) ret.value = FROM_QT(edit->text());

			return ret;
		}
		void Dialog::warn( QWidget * parent, const std::string &title, const std::string &description ){
			Dialog * dlg( new Dialog( title, grabIcon(DI_CRITICAL), parent) );
			dlg->addRow( new QLabel( TO_QT(description), dlg ) );
			dlg->getButtons()->button( QDialogButtonBox::Ok )->setShortcut( Qt::Key_Return );
			dlg->exec();		
		}
		void Dialog::inform( QWidget * parent, const std::string &title, const std::string &description ){
			Dialog * dlg( new Dialog( title, grabIcon(DI_INFORMATION), parent) );
			dlg->addRow( new QLabel( TO_QT(description), dlg ) );
			dlg->getButtons()->button( QDialogButtonBox::Ok )->setShortcut( Qt::Key_Return );
			dlg->exec();
		}

		StringMapReturn Dialog::configure( QWidget * parent, const std::string &title, const StringMapReturn::MapType &settings, IconType type )
		{
			Dialog * dlg( new Dialog( title, grabIcon(type), parent) );

			
			StringMapReturn map;
			QTableWidget* tabl ( new QTableWidget(  dlg ) ); 
			StringMapConnecter * connecter( new StringMapConnecter( map.value, tabl ) );
			
			tabl->verticalHeader()->setVisible( false );
			tabl->setColumnCount( 3 );
			tabl->setHorizontalHeaderLabels( QStringList() << "Property" << "Value" << " " );
			for( auto i=settings.begin(); i!=settings.end(); i++ )
			{
				size_t id = tabl->rowCount();
				tabl->insertRow( id );
				QTableWidgetItem * firstItem(new QTableWidgetItem( TO_QT( i->first ) ));
				QTableWidgetItem * secItem(new QTableWidgetItem( TO_QT( i->second ) ));
				tabl->setItem( id, 0, firstItem );
				tabl->setItem( id, 1, secItem );
				firstItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
				secItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable );
				QPushButton * restoreDefault( new QPushButton(QIcon(":/resources/revert_mini.png"), "Restore Default", tabl) );
				restoreDefault->setToolTip( "Restore Default" );
				restoreDefault->setFixedSize( 16, 16 );
				restoreDefault->setEnabled( false );
				tabl->setCellWidget( id, 2, restoreDefault );
				connecter->map( firstItem, restoreDefault, SIGNAL(triggered(bool)), SLOT(on_restoreDefault_triggered()) );
			}
			dlg->addRow( tabl );
			
			map = StringMapReturn( (StringReturn::Code)dlg->exec(), settings );
			if( map.accepted() )
				map.value = connecter->getSettings();
			return map;
		}
	};
};